package cn.sciento.transfer.infra.rocketmq.vo;

import io.choerodon.mybatis.domain.EntityField;
import java.util.List;
import java.util.stream.Collectors;
import cn.sciento.transfer.infra.datasource.sql.FieldBuilder;
import cn.sciento.transfer.infra.datasource.sql.SqlBuilder;
import org.springframework.beans.BeanWrapperImpl;

public class SqlInfo<S, P> {
  private S sql;
  
  private String type;
  
  private String action;
  
  private P data;
  
  public static SqlInfo<String, List<Object>> builderInsertSqlFromEntity(Object entity, String fullTableName) {
    List<EntityField> entityFieldList = FieldBuilder.buildFieldInDB(entity).stream().filter(item -> {
          BeanWrapperImpl beanWrapper = new BeanWrapperImpl(entity);
          return (beanWrapper.getPropertyValue(item.getName()) != null);
        }).collect(Collectors.toList());
    List<String> columns = (List<String>)entityFieldList.stream().map(EntityField::getName).collect(Collectors.toList());
    String insertSql = SqlBuilder.buildInsert(columns, fullTableName);
    SqlInfo<String, List<Object>> sqlInfo = new SqlInfo<>();
    sqlInfo.setSql(insertSql);
    sqlInfo.setData(FieldBuilder.buildFieldValue(entity, entityFieldList));
    return sqlInfo;
  }
  
  public static SqlInfo<String, List<Object>> builderUpdateSqlFromEntity(Object entity, Object where, String fullTableName) {
    List<EntityField> entityFieldList = FieldBuilder.buildFieldInDB(entity).stream().filter(item -> {
          BeanWrapperImpl beanWrapper = new BeanWrapperImpl(entity);
          return (beanWrapper.getPropertyValue(item.getName()) != null);
        }).collect(Collectors.toList());
    List<String> updateColumns = FieldBuilder.buildFieldName(entity, entityFieldList);
    List<EntityField> whereFiled = FieldBuilder.buildFieldInDB(where).stream().filter(item -> {
          BeanWrapperImpl beanWrapper = new BeanWrapperImpl(where);
          return (beanWrapper.getPropertyValue(item.getName()) != null);
        }).collect(Collectors.toList());
    List<String> whereFieldColumn = FieldBuilder.buildFieldName(where, whereFiled);
    String updateSql = SqlBuilder.buildUpdate(updateColumns, whereFieldColumn, fullTableName);
    List<Object> params = FieldBuilder.buildFieldValue(entity, entityFieldList);
    params.addAll(FieldBuilder.buildFieldValue(where, whereFiled));
    SqlInfo<String, List<Object>> sqlInfo = new SqlInfo<>();
    sqlInfo.setSql(updateSql);
    sqlInfo.setData(params);
    return sqlInfo;
  }
  
  public static SqlInfo<String, List<Object>> builderSelectAllSqlFromEntity(Object entity, String fullTableName, KeyValueBind... valueBinds) {
    List<EntityField> entityFieldList = FieldBuilder.buildFieldInDB(entity).stream().filter(item -> {
          BeanWrapperImpl beanWrapper = new BeanWrapperImpl(entity);
          return (beanWrapper.getPropertyValue(item.getName()) != null);
        }).collect(Collectors.toList());
    String selectSqlFromEntity = SqlBuilder.buildSelectAllColumn(FieldBuilder.buildFieldName(entity, entityFieldList), fullTableName);
    KeyValueBind[] binds = (valueBinds == null) ? new KeyValueBind[0] : valueBinds;
    StringBuilder whereFormBinds = new StringBuilder();
    for (int i = 0; i < binds.length; i++)
      whereFormBinds.append(" and ").append(binds[i].toString()); 
    String sql = selectSqlFromEntity + whereFormBinds.toString();
    List<Object> params = FieldBuilder.buildFieldValue(entity, entityFieldList);
    for (int j = 0; j < binds.length; j++)
      params.add(binds[j].getValue()); 
    SqlInfo<String, List<Object>> sqlInfo = new SqlInfo<>();
    sqlInfo.setSql(sql);
    sqlInfo.setData(params);
    return sqlInfo;
  }
  
  public static SqlInfo<String, List<Object>> builderDeleteSqlFromEntity(Object entity, String fullTable) {
    List<EntityField> entityFieldList = FieldBuilder.buildFieldInDB(entity).stream().filter(item -> {
          BeanWrapperImpl beanWrapper = new BeanWrapperImpl(entity);
          return (beanWrapper.getPropertyValue(item.getName()) != null);
        }).collect(Collectors.toList());
    String sql = SqlBuilder.buildDelete(FieldBuilder.buildFieldName(entity, entityFieldList), fullTable);
    List<Object> params = FieldBuilder.buildFieldValue(entity, entityFieldList);
    SqlInfo<String, List<Object>> sqlInfo = new SqlInfo<>();
    sqlInfo.setSql(sql);
    sqlInfo.setData(params);
    return sqlInfo;
  }
  
  public String getType() {
    return this.type;
  }
  
  public void setType(String type) {
    this.type = type;
  }
  
  public S getSql() {
    return this.sql;
  }
  
  public void setSql(S sql) {
    this.sql = sql;
  }
  
  public P getData() {
    return this.data;
  }
  
  public void setData(P data) {
    this.data = data;
  }
  
  public String getAction() {
    return this.action;
  }
  
  public void setAction(String action) {
    this.action = action;
  }
  
  public static class KeyValueBind {
    private String key;
    
    private Object value;
    
    private String pattern;
    
    public KeyValueBind(String key, Object value, String pattern) {
      this.key = key;
      this.value = value;
      this.pattern = pattern;
    }
    
    public String getKey() {
      return this.key;
    }
    
    public Object getValue() {
      return this.value;
    }
    
    public String toString() {
      return " " + FieldBuilder.formatFieldToColumn(this.key) + " " + this.pattern + " ? ";
    }
  }
}
